package com.cizzy.video.recommend;

import com.cizzy.video.feign.FavoriteFeign;
import com.cizzy.video.feign.UserFeign;
import com.cizzy.video.service.IVideoService;
import jakarta.annotation.Resource;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.List;

import static com.cizzy.video.config.CizzyFinal.RECOMMEND_USER_LIMIT;
import static com.cizzy.video.config.CizzyFinal.RECOMMEND_VIDEO_LIMIT;

public class VideoRecommendation implements Runnable {
    @Resource
    private UserFeign userFeign;

    @Resource
    private FavoriteFeign favoriteFeign;

    @Autowired
    private RedisTemplate redisTemplate;

    @Resource
    private IVideoService videoService;
    public void run() {
        while(true) {
            try {
                Thread.sleep(360000L);
                List<Long> userIdList = userFeign.getRandomUserIdList(RECOMMEND_USER_LIMIT).getData();
                List<Long> videoIdList = videoService.getRandomVideoIdList(RECOMMEND_VIDEO_LIMIT).getData();
                FastByIDMap<PreferenceArray> preferences = new FastByIDMap<PreferenceArray>();
//                PreferenceArray User1Pref = new GenericUserPreferenceArray(2);
//                GenericDataModel dataModel = new GenericDataModel();
                for(int i = 0; i < userIdList.size(); i++) {
                    PreferenceArray userPreferenceArray = new GenericUserPreferenceArray(videoIdList.size());
                    userPreferenceArray.setUserID(i, userIdList.get(i));
                    for(int j = 0; j < videoIdList.size(); j++) {
                        userPreferenceArray.setItemID(j, videoIdList.get(j));
                        if (favoriteFeign.isFavorited(userIdList.get(i), videoIdList.get(j)).getData()) {
                            userPreferenceArray.setValue(j, 1L);
                        } else {
                            userPreferenceArray.setValue(j, 0L);
                        }
                    }
                }
                DataModel model = new GenericDataModel(preferences);
                ItemSimilarity item = new EuclideanDistanceSimilarity(model);
                Recommender r = new GenericItemBasedRecommender(model,item);

                LongPrimitiveIterator iter = model.getUserIDs();

                while(iter.hasNext())
                {
                    long uid = iter.nextLong();
                    List<RecommendedItem> list = r.recommend(uid, 1);  //获取推荐结果
                    //遍历推荐结果
                    for(RecommendedItem ritem : list)
                    {
//                        System.out.printf("(%s,%f)",ritem.getItemID(),ritem.getValue());
                        if(redisTemplate.hasKey(uid)) {
                            if(redisTemplate.opsForList().size(uid) < 10) {
                                redisTemplate.opsForList().rightPush(uid, ritem.getItemID());
                            }
                        } else {
                            redisTemplate.opsForList().rightPush(uid, ritem.getItemID());
                        }
                    }
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } catch (TasteException e) {
                throw new RuntimeException(e);
            }
        }
    }
}